﻿using BCCommon;
using BCCommon.NPinyin;
using BCData.TMS.Agent.AgentAreaRecord;
using BCData.TMS.MoveHouseConfig.MoveHouseConfig;
using BCData.TMS.MoveHouseConfig.MoveHouseSpecificationConfig;
using BCData.TMS.MoveHouseConfig.MoveHouseSpecificationServiceConfig;
using BCData.TMS.MoveHouseConfig.MoveHouseSpecificationServiceConfigOverWrite;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.MoveHouseConfig.MoveHouseConfig;
using BCDto.TMS.MoveHouseConfig.MoveHouseConfig.MoveHouseConfigRequest;
using BCEntity.Common.Area;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.MoveHouseConfig.MoveHouseConfig;
using BCService.Common.Area;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace BCService.TMS.MoveHouseConfig.MoveHouseConfig
{
    public class MoveHouseConfigService : IMoveHouseConfigService
    {
        private readonly IDatabaseContext databaseContext;
        private readonly IMoveHouseConfigData moveHouseConfigData;
        private readonly IRedisService redisService;
        private readonly IMoveHouseSpecificationConfigData moveHouseSpecificationConfigData;
        private readonly IZoneService zoneService;
        private readonly IMoveHouseSpecificationServiceConfigData moveHouseSpecificationServiceConfigData;
        private readonly IMoveHouseSpecificationServiceConfigOverWriteData moveHouseSpecificationServiceConfigOverWriteData;
        private readonly IAgentAreaRecordData agentAreaRecordData;
        private readonly string key = string.Format("{0}", EntityNameConst.MoveHouseConfigEntity);
        private readonly string keyMinPrice = string.Format("{0}", EntityNameConst.MoveHouseMinPriceEntity);
        public MoveHouseConfigService(IDatabaseContext databaseContext,
            IMoveHouseConfigData moveHouseConfigData,
            IRedisService redisService,
            IMoveHouseSpecificationConfigData moveHouseSpecificationConfigData,
            IZoneService zoneService,
            IAgentAreaRecordData agentAreaRecordData,
            IMoveHouseSpecificationServiceConfigData moveHouseSpecificationServiceConfigData,
            IMoveHouseSpecificationServiceConfigOverWriteData moveHouseSpecificationServiceConfigOverWriteData)
        {
            this.databaseContext = databaseContext;
            this.moveHouseConfigData = moveHouseConfigData;
            this.redisService = redisService;
            this.moveHouseSpecificationConfigData = moveHouseSpecificationConfigData;
            this.zoneService = zoneService;
            this.agentAreaRecordData = agentAreaRecordData;
            this.moveHouseSpecificationServiceConfigData = moveHouseSpecificationServiceConfigData;
            this.moveHouseSpecificationServiceConfigOverWriteData = moveHouseSpecificationServiceConfigOverWriteData;
        }

        public MoveHouseConfigViewDto Create(MoveHouseConfigRequestDto requestDto, AdminDto admin)
        {
            MoveHouseConfigEntity parentEntity = null;
            var entity = new MoveHouseConfigEntity
            {
                MoveHouseConfigName = requestDto.MoveHouseConfigName,
                MoveHouseConfigPinYin = Pinyin.GetCompactPinyin(requestDto.MoveHouseConfigName),
                Remark = requestDto.Remark,
                Enabled = true,
                IsParent = false,
                Level = 0,
                ParentId = requestDto.ParentId,
                AllParentId = requestDto.ParentId.ToString(),
                CreateTime = DateTime.Now,
                CreateAdminId = admin.AdminId,
                CreateAdminName = admin.FullName,
                UpdateTime = DateTime.Now,
                EditAdminId = admin.AdminId,
                EditAdminName = admin.FullName,
            };
            if (requestDto.ParentId > 0)
            {
                entity.Level = 1;
                entity.AllParentId = "0," + requestDto.ParentId.ToString();
                parentEntity = this.moveHouseConfigData.GetSingle(requestDto.ParentId).Result;
                parentEntity.IsParent = true;
                entity.PhotoAddress = requestDto.PhotoAddress;
            }
            this.databaseContext.BeginTransaction();
            var result = this.moveHouseConfigData.InsertAsync(entity).GetAwaiter().GetResult();
            if (parentEntity != null)
            {
                moveHouseConfigData.UpdateAsync(parentEntity).GetAwaiter().GetResult();
            }
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(key, false);
            return result.As<MoveHouseConfigViewDto>();
        }

        public bool Delete(long moveHouseConfigId, AdminDto admin)
        {
            var entity = moveHouseConfigData.GetSingle(moveHouseConfigId).Result;
            if (entity == null)
            {
                throw new ArgumentException(" 获取搬家设置信息失败 ");
            }
            if (entity.IsParent)
            {
                throw new ArgumentException(" 当前搬家设置存在子级,不可删除 ");
            }
            var moveHouseSpecificationConfig = this.moveHouseSpecificationConfigData.GetList(moveHouseConfigId, true).Result;
            if (moveHouseSpecificationConfig.Any())
            {
                throw new ArgumentException(" 当前搬家设置存在规格,不可删除 ");
            }
            if (admin.CompanyId != 1)
            {
                throw new ArgumentException(" 代理商不可删除搬家设置 ");
            }
            this.databaseContext.BeginTransaction();
            var result = moveHouseConfigData.DeleteAsync(moveHouseConfigId).GetAwaiter().GetResult();
            if (result > 0 && entity.ParentId > 0)
            {
                var parentEntity = this.moveHouseConfigData.GetSingle(entity.ParentId).Result;
                parentEntity.IsParent = false;
                moveHouseConfigData.UpdateAsync(parentEntity).GetAwaiter().GetResult();
            }
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(key, false);
            return true;
        }

        public IEnumerable<MoveHouseConfigViewDto> GetList(int parentId, bool? isEnable, int level)
        {
            string cacheKey = this.redisService.GetKey(key, parentId, isEnable, level);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = moveHouseConfigData.GetList(parentId, isEnable, level).Result;
                return data;
            }, TimeSpan.FromDays(1));
            return result.As<IEnumerable<MoveHouseConfigViewDto>>();
        }

        public IEnumerable<MoveHouseConfigViewDto> GetAllList(bool? isEnable, int level)
        {
            var moveHouseConfig = new MoveHouseConfigViewDto()
            {
                MoveHouseConfigId = 0,
                MoveHouseConfigName = "全部",
                IsAll = true,
            };
            string cacheKey = this.redisService.GetKey(key, isEnable, 0);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = moveHouseConfigData.GetAllList(isEnable, 0).Result.As<IEnumerable<MoveHouseConfigViewDto>>().ToList();
                if (data.FirstOrDefault() != null)
                {
                    moveHouseConfig.Level = data.FirstOrDefault().Level;
                }
                data.Add(moveHouseConfig);
                var tempData= data.OrderBy(p => p.MoveHouseConfigId).ToList();
                foreach (var item in tempData)
                {
                    if (item.MoveHouseConfigId != 0) continue;
                    var tempMoveHouseConfig = new MoveHouseConfigViewDto()
                    {
                        MoveHouseConfigId = 0,
                        MoveHouseConfigName = "全部",
                        Level = item.Level + 1,
                        IsAll = true,
                    };
                    item.MoveHouseConfigs.Add(tempMoveHouseConfig);
                    item.MoveHouseConfigs.AddRange(moveHouseConfigData.GetAllSecondList(isEnable).Result.As<IEnumerable<MoveHouseConfigViewDto>>());
                }
                return tempData;
            }, TimeSpan.FromDays(1));
          
            return result;
        }

        public IEnumerable<MoveHouseConfigViewDto> GetList(long moveHouseConfigId, bool? isEnable, int level)
        {
            var moveHouseConfig = new MoveHouseConfigViewDto
            {
                MoveHouseConfigId = moveHouseConfigId,
                MoveHouseConfigName = "全部",
                IsAll = true,
            };
            string cacheKey = this.redisService.GetKey(key, moveHouseConfigId, isEnable, level);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = moveHouseConfigData.GetList(moveHouseConfigId, isEnable, level).Result.As<IEnumerable<MoveHouseConfigViewDto>>().ToList();
                var tempData= data.OrderBy(p => p.MoveHouseConfigId).ToList();
                foreach (var item in tempData)
                {
                    moveHouseConfig.Level = item.Level + 1;
                    item.MoveHouseConfigs.Add(moveHouseConfig);
                    item.MoveHouseConfigs.AddRange(moveHouseConfigData.GetList(item.MoveHouseConfigId, isEnable, 1).Result.As<IEnumerable<MoveHouseConfigViewDto>>());
                }
                return tempData;
            }, TimeSpan.FromDays(1));
           
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="moveHouseConfigId"></param>
        /// <returns></returns>
        public MoveHouseConfigViewDto GetSingle(long moveHouseConfigId)
        {
            string cacheKey = this.redisService.GetKey(key, moveHouseConfigId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var entity = moveHouseConfigData.GetSingle(moveHouseConfigId).Result;
                return entity.As<MoveHouseConfigViewDto>();
            }, TimeSpan.FromDays(1));
            return result;
        }

        public PageableList<MoveHouseConfigViewDto> Query(int parentId, bool? isEnable, int level, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, parentId, isEnable, level, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var (list, count) = moveHouseConfigData.Query(parentId, isEnable, level, pageIndex, pageSize).Result;
                return new PageableList<MoveHouseConfigViewDto>()
                {
                    Items = list.As<IEnumerable<MoveHouseConfigViewDto>>(),
                    Count = count
                };
            }, TimeSpan.FromDays(1));
            return result;
        }
        public IEnumerable<MoveHouseConfigViewDto> GetAllSecondList(bool? isEnable)
        {
            string cacheKey = this.redisService.GetKey(key, isEnable);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = new List<MoveHouseConfigViewDto>();
                var moveHouseConfig = new MoveHouseConfigViewDto()
                {
                    MoveHouseConfigId = 0,
                    MoveHouseConfigName = "全部",
                    Level = 1,
                    IsAll = true,
                };
                result.Add(moveHouseConfig);
                var data = moveHouseConfigData.GetAllSecondList(isEnable).Result.As<IEnumerable<MoveHouseConfigViewDto>>();
                result.AddRange(data);
                return result;
            }, TimeSpan.FromDays(1));

            return resultRedis;
        }

        public IEnumerable<MoveHouseConfigViewDto> GetAllClientList(string countyCode)
        {
            if (string.IsNullOrWhiteSpace(countyCode))
            {
                throw new ArgumentException("请选择要设置业务的行政区域!");
            }
            var zoneEntity = this.zoneService.GetFromZoneEntity(countyCode);
            if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("此区域信息不正确!");
            }
            var agentAreaRecord = this.agentAreaRecordData.GetLastLevelByCode(zoneEntity.countyEntity.CountyCode).Result;
            if (agentAreaRecord == null)
            {
                throw new ArgumentException(" 当前行政区域不属于管辖范围 ");
            }
            string cacheKey = this.redisService.GetKey(key, 0);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = moveHouseConfigData.GetAllClientList(0).Result.As<IEnumerable<MoveHouseConfigViewDto>>().ToList();
                var minPriceList = GetMinPrice(zoneEntity, agentAreaRecord.AgentRecordId);
                foreach (var item in data)
                {
                    var moveHouseConfigs = moveHouseConfigData.GetAllClientList(item.MoveHouseConfigId).Result.As<IEnumerable<MoveHouseConfigViewDto>>().ToList();
                    foreach (var itemConfig in moveHouseConfigs)
                    {
                        var basePrice = minPriceList.FirstOrDefault(p => p.MoveHouseConfigId == itemConfig.MoveHouseConfigId);
                        itemConfig.BasePrice = basePrice == null ? 0 : basePrice.Price;
                    }
                    item.MoveHouseConfigs = moveHouseConfigs;
                }
                return data;
            }, TimeSpan.FromDays(1));
            return result;
        }

        private List<MoveHouseMinPriceDto> GetMinPrice(ZoneEntity zoneEntity, long agentRecordId)
        {
            string cacheKey = this.redisService.GetKey(keyMinPrice, true);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                List<MoveHouseMinPriceDto> list = new List<MoveHouseMinPriceDto>();
                var moveHouseMinPrices = moveHouseSpecificationServiceConfigData.GetMinPrice(true).Result;
                var moveHouseMinPriceOverWrites = moveHouseSpecificationServiceConfigOverWriteData.GetMinPrice(zoneEntity.provinceEntity.ProvinceCode,
                    zoneEntity.cityEntity.CityCode, zoneEntity.countyEntity.CountyCode, agentRecordId, true).Result.ToList();
                foreach (var item in moveHouseMinPrices)
                {
                    var entity = new MoveHouseMinPriceDto()
                    {
                        MoveHouseConfigId = item.MoveHouseConfigId,
                        Price = item.Price,
                    };
                    var overWrite = moveHouseMinPriceOverWrites.FirstOrDefault(p => p.MoveHouseConfigId == item.MoveHouseConfigId);
                    if (overWrite != null && overWrite.Price < item.Price)
                    {
                        entity.Price = overWrite.Price;
                    }
                    list.Add(entity);
                }
                return list;
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }
        public bool UpdatePhoto(long moveHouseConfigId, MoveHouseConfigPhotoRequestDto requestDto, AdminDto admin)
        {
            var entity = moveHouseConfigData.GetSingle(moveHouseConfigId).Result;
            if (entity == null)
            {
                throw new ArgumentException(" 获取搬家设置信息失败 ");
            }
            if (entity.IsParent)
            {
                throw new ArgumentException(" 当前搬家设置是父级,不可设置图片 ");
            }
            entity.PhotoAddress = requestDto.PhotoAddress;
            entity.UpdateTime = DateTime.Now;
            entity.EditAdminId = admin.AdminId;
            entity.EditAdminName = admin.FullName;
            this.moveHouseConfigData.UpdateAsync(entity).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return true;
        }

        public bool Enabled(long moveHouseConfigId, AdminDto admin)
        {
            if (admin.CompanyId != 1)
            {
                throw new ArgumentException(" 用户认证失败,错误操作 ");
            }
            var entity = moveHouseConfigData.GetSingle(moveHouseConfigId).Result;
            if (entity == null)
            {
                throw new ArgumentException(" 获取搬家设置信息失败 ");
            }
            if (!entity.IsParent && entity.ParentId > 0)
            {
                var parentEntity = moveHouseConfigData.GetParentSingle(entity.ParentId).Result;
                if (!parentEntity.Enabled)
                {
                    throw new ArgumentException(" 获取搬家设置父级被禁用,不可启用 ");
                }
            }
            entity.Enabled = true;
            entity.UpdateTime = DateTime.Now;
            entity.EditAdminId = admin.AdminId;
            entity.EditAdminName = admin.FullName;
            this.moveHouseConfigData.UpdateAsync(entity).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return true;
        }

        public bool Disabled(long moveHouseConfigId, AdminDto admin)
        {
            if (admin.CompanyId != 1)
            {
                throw new ArgumentException(" 用户认证失败,错误操作 ");
            }
            var entity = moveHouseConfigData.GetSingle(moveHouseConfigId).Result;
            if (entity == null)
            {
                throw new ArgumentException(" 获取搬家设置信息失败 ");
            }
            if (entity.IsParent)
            {
                throw new ArgumentException(" 当前搬家设置存在子级,不可禁用 ");
            }
            else
            {
                var entities = moveHouseSpecificationConfigData.GetList(moveHouseConfigId, null).Result;
                if (entities.Any())
                {
                    throw new ArgumentException(" 当前搬家设置存在规格,不可禁用 ");
                }
            }
            entity.Enabled = false;
            entity.UpdateTime = DateTime.Now;
            entity.EditAdminId = admin.AdminId;
            entity.EditAdminName = admin.FullName;
            this.moveHouseConfigData.UpdateAsync(entity).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return true;
        }
    }
}
